![]() |
![]() |
|
Nehmen wir an, eine Anwendung hätte die globale Assembly MyAssembly eingebunden, deren Version 1.0.0.0 sei. MyAssembly ist im Manifest der Anwendung aufgeführt, einschließlich des öffentlichen Schlüssels und der Versionsnummer. Nehmen wir weiter an, dass auf demselben Computer bereits die neueren Versionen 1.0.1.0 und 1.0.2.0 von MyAssembly installiert sind. Nach der Installation befinden sich somit insgesamt drei verschiedene Versionen der globalen Assembly im GAC. Wird die Anwendung gestartet, ist zunächst das Manifest ausschlaggebend dafür, welche Version der Assembly geladen werden soll. Die Laufzeitumgebung merkt sich die Version und sucht anschließend nach einer Anwendungskonfigurationsdatei. Ist eine solche im Anwendungsverzeichnis gespeichert und enthält sie einen Eintrag, der die Umleitung zu einer anderen Version beschreibt, überschreibt der Eintrag in der Anwendungskonfigurationsdatei den Eintrag im Manifest. Nach der Suche und der Auswertung der Anwendungskonfigurationsdatei interessiert sich die Laufzeit für eine möglicherweise existierende Publisher-Richtliniendatei von MyAssembly. Hat der Entwickler der Assembly eine solche bereitgestellt und ist sie im GAC installiert, überschreibt deren Versionsangabe diejenige, die bis zu diesem Zeitpunkt gültig war. Im letzten Schritt durchforstet die Laufzeit die Computerkonfigurationsdatei, die im Gegensatz zu den beiden vorher aufgeführten nicht optional ist. Hat der Anwender in machine.config eine Versionsumleitung eingetragen (dazu sind administrative Rechte notwendig), gilt diese vor allen anderen.
Abbildung 27.1 Die Aufrufreihenfolge der Konfigurationsdateien Entscheidend dafür, auf welche Assembly-Version die Anwendung zugreift, ist der zuletzt gefundene Eintrag. Sollen alle Anwendungen grundsätzlich mit einer bestimmten Version arbeiten, genügt ein Eintrag in die Computerkonfigurationsdatei, falls der Hersteller der Komponente nicht selbst für eine Publisher-Richtliniendatei gesorgt hat. Auf eine Anwendungskonfigurationsdatei kann in diesem Fall verzichtet werden – es sei denn, andere Vorgaben oder Einstellungen müssen getroffen werden, die nichts mit dem Versionsaufruf zu tun haben. Es könnte auch passieren, dass in der Computerkonfigurationsdatei die Umleitung auf eine Version von MyAssembly angegeben ist, die sich aber als nicht abwärtskompatibel für eine ganz bestimmte Anwendung erweist, während andere Anwendungen problemlos damit zusammenarbeiten können. Dann besteht die Möglichkeit, in der Anwendungskonfigurationsdatei der betroffenen Anwendung den Automatismus der Versionsumleitung abzuschalten. 27.1.3 Die Struktur einer Anwendungskonfigurationsdatei
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <?xml version="1.0" encoding="utf-8" ?> |
| <configuration> |
| <system.diagnostics> |
| ... |
| </system.diagnostics> |
| </configuration> |
Mit der ersten Zeile, die als XML-Deklaration oder auch als Prolog bezeichnet wird, wird der Einstiegspunkt in das XML-Dokument festgelegt. Neben der Versionsnummer wird auch der zum Lesen des Dokuments verwendete Zeichensatz, hier UTF-8, beschrieben.
Jedes XML-Dokument hat ein so genanntes Stammelement. Bei den Konfigurationsdateien ist es das <configuration>-Element. Alle Informationen, die zwischen dem einleitenden und dem ausleitenden Tag stehen und ihrerseits selbst Elemente sind, werden dazu benutzt, die Anwendung zu konfigurieren.
Ich möchte Ihnen nun eine Konfigurationsdatei zeigen, die nicht nur den erforderlichen Strukturrahmen aufweist, sondern gleichzeitig auch bereits Informationen in sich birgt.
| <?xml version="1.0" encoding="utf-8" ?> |
| <configuration> |
| <configSections> |
| <sectionGroup name="userSettings" |
| type="System.Configuration.UserSettingsGroup, |
| ... > |
| <section name="WinApp.My.MySettings" ... /> |
| </sectionGroup> |
| <sectionGroup name="applicationSettings" |
| ... > |
| <section name="WinApp.My.MySettings" ... /> |
| </sectionGroup> |
| </configSections> |
| <userSettings> |
| <WinApp.My.MySettings> |
| <setting name="Variable1" serializeAs="String"> |
| <value /> |
| </setting> |
| </WinApp.My.MySettings> |
| </userSettings> |
| <applicationSettings> |
| <WinApp.My.MySettings> |
| <setting name="Variable2" serializeAs="String"> |
| <value /> |
| </setting> |
| </WinApp.My.MySettings> |
| </applicationSettings> |
| </configuration> |
Dieser Anwendungskonfigurationsdatei liegt eine Windows-Anwendung mit dem Bezeichner WinApp zugrunde. Der besseren Übersicht wegen sind einige unwesentliche Passagen nur gekürzt wiedergegeben.
Innerhalb von <configuration> sind drei Sektionen definiert:
| <configSections> |
| <userSettings> |
| <applicationSettings> |
<configSections> gibt die diesem Element folgenden Konfigurationsabschnitte an und ist immer das direkt <configuration> untergeordnete Element.
Die Notationen in den beiden Abschnitten <applicationSettings> und <userSettings> sind identisch. Zunächst wird ein neuer untergeordneter Abschnitt eröffnet, der eine Klasse angibt, hier z. B.:
| WindowsApplication1.My.MySettings |
Die Klasse heißt MySettings, der Namespace ist WindowsApplication1.My. Namespace und Klasse werden von Visual Studio automatisch erzeugt. MySettings definiert hauptsächlich Eigenschaftsmethoden, um den Zugriff auf die in der Konfigurationsdatei abgelegten Daten zu ermöglichen.
Die untergeordneten <setting>-Elemente beschreiben mit dem Attribut name den Bezeichner der gespeicherten Variablen, serializeAs gibt den Datentyp an. Meist werden die Daten als Zeichenfolge serialisiert, ansonsten sind auch noch xml, binary und custom mögliche Alternativen. Das Tag <value> schließlich beschreibt den gespeicherten Wert.
Benutzerunabhängige Daten sind in der Sektion <applicationSettings> festgelegt. Alle Informationen, die dieser Abschnitt beschreibt, gelten uneingeschränkt für jeden Benutzer der Anwendung. Im Beispiel oben wird nur eine Dateninformation in diesem Abschnitt festgelegt, welche die Bezeichnung Variable2 hat und die Zeichenfolge 25 beschreibt. Es könnte sich dabei allerdings auch um einen beliebigen anderen Datentyp handeln.
Variable2 kann beim Starten der Anwendung ausgewertet und von der laufenden Anwendung weiterverarbeitet werden. Solange sich nichts am Inhalt von Variable2 ändert, käme das der Deklaration einer gleichnamigen Variablen im Code gleich. Sollte jedoch ein abweichender Wert wünschenswert sein, kann dieser in der Konfigurationsdatei geändert werden, ohne dass eine Neukompilierung erforderlich ist. Ein besonderes Charakteristikum von <applicationSettings> ist, dass sich die Werte nicht mittels Code aus einer laufenden Anwendung heraus editieren lassen. Änderungen sind nur über einen entsprechenden Editor möglich. Weiter unten in diesem Kapitel werde ich Ihnen aber mit dem ähnlich lautenden Abschnitt <appSettings> eine Möglichkeit zeigen, dennoch anwendungsspezifische Daten in einer Konfigurationsdatei mittels Code zu manipulieren.
<applicationSettings> ist denkbar ungeeignet, benutzerspezifische Einstellungen zu speichern. Abgesehen von der schnell wachsenden Größe der Konfigurationsdatei bei steigender Benutzeranzahl würde der Inhalt auch jedem anderen Benutzer offengelegt wie ein Buch. Deshalb werden benutzereigene Einstellungen in der Sektion <userSettings> der Anwendungskonfigurationsdatei beschrieben. Daten, die hier eingetragen sind, gelten als Standardwerte für den jeweiligen Anwender. Kommt es zu einer Änderung der Daten, werden diese in einer Datei mit dem Namen user.config im jeweiligen Windows-Benutzerprofil unter
Dokumente und Einstellungen\<Benutzer>\Lokale Einstellungen\Anwendungsdaten\ <Firma>\<Anwendung>
gespeichert. Daraus können Sie auch schlussfolgern, dass im Gegensatz zu <applicationSettings> die Daten, die im Abschnitt <userSettings> definiert sind, mittels Code verändert werden können.
Eine Konfigurationsdatei wie die oben beschriebene müssen Sie natürlich nicht mit dem MS Editor oder ähnlichen Programmen mühevoll selbst schreiben. Greifen Sie besser auf die Fähigkeiten von Visual Studio 2005 zurück.
Öffnen Sie dazu den Knoten My Project im Projektmappen-Explorer und klicken auf Settings.settings doppelt. In dem sich daraufhin öffnenden Fenster können Sie auf einfachste Weise die Einträge der Abschnitte <userSettings> und <applicationSettings> vornehmen. In der Spalte Name tragen Sie den Namen der Variablen ein, und unter Typ legen Sie den Datentyp fest. Ob es sich um eine allgemeine oder um eine benutzerspezifische Variable handelt, wählen Sie aus der der Spalte Bereich zugeordneten Liste aus. In der letzten Spalte können Sie auch den Startwert der Variablen bestimmen. Eine Vorgabe ist hier nicht notwendig.

Hier klicken, um das Bild zu Vergrößern
Abbildung 27.2 Festlegen der Konfigurationseinstellungen im Visual Studio 2005
Die Sektionen in einer Anwendungskonfigurationsdatei beschränken sich nicht nur auf die zuvor aufgeführten <configSettings>, <applicationSettings> und <userSettings>. Darüber hinaus stehen Ihnen weitere Abschnitte zur Verfügung, um die Sie die Konfigurationsdatei ebenfalls optional erweitern können. Darüber hinaus können Sie auch eigene Sektionen definieren.
Zwei vordefinierte Sektionen seien an dieser Stelle genannt:
| <connectionStrings> |
| <appSettings> |
<connectionStrings> ist ein Konfigurationselement, das die Ablage mehrerer Verbindungszeichenfolgen für ADO.NET erlaubt. Damit ist es möglich, zur Laufzeit einer Anwendung unter Umständen sogar aus einer längeren Auswahlliste den gewünschten Produktionsdatenbankserver auszuwählen.
<appSettings> gab es bereits unter .NET Framework 1.0/1.1. Es erfüllt die gleiche Aufgabe wie die Sektion <applicationSettings>, ist aber dazu befähigt, aus dem Code der laufenden Anwendung heraus editierbar zu sein.
Die Möglichkeiten, Einfluss auf eine .NET-Anwendung über eine Konfigurationsdatei auszu-üben, sind jedoch noch weitaus größer. Sie können beispielsweise einen Abschnitt <startup> festlegen, der die von der Anwendung unterstützte Version der CLR beschreibt. Den optionalen Abschnitt <runtime> lernen Sie weiter unten noch kennen. Er enthält Informationen über Assembly-Bindungen.
In vielen WinForm-Anwendungen werden Sie Daten insbesondere für den angemeldeten User speichern wollen. Beispielsweise möchten Sie gewährleisten, dass die Position und Größe eines Fensters bei einem Neustart der Anwendung so wiederhergestellt werden, wie sie beim Schließen der Anwendung waren. Vielleicht sollen auch noch weitere Zustände vollständig restauriert werden, beispielsweise der Inhalt diverser Textboxen.
Natürlich können Sie jede in der Konfigurationsdatei zu speichernde Einstellung im Dialog Settings.settings eintragen (siehe Abbildung 27.2). Im Eigenschaftsfenster der GUI-Komponenten wird Ihnen jedoch mit ApplicationSettings eine einfachere und intuitivere Alternative angeboten. In einem Dialog können Sie zuerst die Eigenschaft auswählen, deren Einstellung Sie in der Konfigurationsdatei speichern wollen. Bei der Wahl wird Ihnen ein zweiter Dialog angeboten, in dem Sie einen Standardwert eintragen können und den Bezeichner der Einstellung festlegen. Sie müssen sich auch entscheiden, ob die Einstellung benutzerspezifisch (User) ist oder auf Anwendungsebene gilt (Application).

Hier klicken, um das Bild zu Vergrößern
Abbildung 27.3 Festlegen einer Eigenschaftseinstellung für die Speicherung in der Konfigurationsdatei
Mit den in Abbildung 27.3 gezeigten Einstellungen wird die App.config-Datei um den folgenden Eintrag im Abschnitt <userSettings> ergänzt.
| <userSettings> |
| <WinApp.My.MySettings> |
| <setting name="Textbox1Inhat" serializeAs="String"> |
| <value /> |
| </setting> |
| </WinApp.My.MySettings> |
| </userSettings> |
Das Element value weist hier keinen Eintrag auf, weil unter DefaultValue keine Angabe gemacht worden ist. Ein Eintrag wäre als Standardwert für jeden Benutzer so lange gültig, bis der Benutzer einen individuellen Wert speichert. Wie Sie wissen, werden alle vom Standard abweichenden Einträge im Abschnitt <userSettings> in user.config abgelegt.
Im folgenden Beispiel enthält eine WinForm drei Textboxen, in denen der Benutzer seine Adressdaten eintragen kann. Um die vorgenommenen Einträge zu speichern, muss er das Häkchen in der Checkbox setzen. Die Daten sollen dann natürlich in der benutzereigenen user.config-Datei gespeichert werden. In jeder der Textboxen wird, solange keine benutzerspezifischen Daten vorliegen, ein Standardtext angezeigt. Darüber hinaus wird auch die aktuelle Position des Fensters während des Schließvorgangs gespeichert.
Die Beschriftung der Titelleiste der Form soll einem Eintrag in der Konfigurationsdatei entnommen werden, der anwendungsbezogen ist. Im ersten Moment ist das natürlich kein großer Vorteil, aber es wird damit die Option offengehalten, durch Änderung des Eintrags in der Konfigurationsdatei allen Benutzern eine von der Vorgabe abweichende Titelleistenbeschriftung anzuzeigen, ohne den Code neu kompilieren zu müssen. Wie Sie wissen, muss die Anwendungskonfigurationsdatei dazu nur mit einem passenden Editor geöffnet werden.

Hier klicken, um das Bild zu Vergrößern
Abbildung 27.4 Ausgabe des Beispiels »UserSettingsDemo«
Die in der Entwicklungsumgebung resultierende Datei app.config sehen wir uns nun an. Aus Gründen der Übersichtlichkeit ist auch hier wiederum der Abschnitt <configSections> stark gekürzt. Sie können sich aber bei Interesse die vollständigen Einträge im Beispielcode der Anwendung UserSettingsDemo auf der Buch-CD ansehen.
| <?xml version="1.0" encoding="utf-8" ?> |
| <configuration> |
| <configSections> |
| <sectionGroup name="userSettings" ... > |
| <section name="UserSettingsDemo.My.MySettings" ... /> |
| </sectionGroup> |
| <sectionGroup name="applicationSettings" ... > |
| <section name="UserSettingsDemo.My.MySettings" ... /> |
| </sectionGroup> |
| </configSections> |
| <userSettings> |
| <UserSettingsDemo.My.MySettings> |
| <setting name="Name" serializeAs="String"> |
| <value><ihr Name></value> |
| </setting> |
| <setting name="wohnort" serializeAs="String"> |
| <value><ihr Wohnort></value> |
| </setting> |
| <setting name="strasse" serializeAs="String"> |
| <value><ihre Strasse></value> |
| </setting> |
| </UserSettingsDemo.My.MySettings> |
| </userSettings> |
| <applicationSettings> |
| <UserSettingsDemo.My.MySettings> |
| <setting name="titelleiste" serializeAs="String"> |
| <value>UserSettingsDemo</value> |
| </setting> |
| </UserSettingsDemo.My.MySettings> |
| </applicationSettings> |
| </configuration> |
Die Speicherung der Textboxeinträge in user.config erfolgt, wenn der Anwender das Fenster schließt. Hier bietet sich das Ereignis FormClosing der Form an. Für das Speichern ist nach vorheriger Prüfung der Checkbox nur eine Anweisungszeile notwendig. Das Laden der gespeicherten Daten erfolgt automatisch, ohne dass Sie dafür auch nur eine Codezeile schreiben müssen.
| ' --------------------------------------------------------- |
| ' Beispiel: ...\Kapitel 27\UserSettingsDemo |
| ' --------------------------------------------------------- |
| Private Sub Form1_FormClosing(ByVal sender As Object, _ |
| ByVal e As FormClosingEventArgs) Handles Me.FormClosing |
| If Me.chkPersist.Checked = True Then |
| My.MySettings.Default.Save() |
| End If |
| End Sub |
Wenn es Sie interessiert, auf welcher Grundlage diese Anweisung basiert, öffnen Sie die Datei Settings.Designer.vb, die Sie innerhalb des Knotens My Project im Projektmappen-Explorer finden. Diese Datei wird von Visual Studio 2005 generiert. Für sie gilt dasselbe wie auch für die Methode InitializeComponent einer WinForm: Ändern Sie sie nicht, um nicht unliebsame Überraschungen zu erleben.
Settings.Designer.vb enthält die Beschreibung der Klasse MySettings, die von ApplicationSettingsBase abgeleitet ist. Diese Klasse ist ein Wrapper um die Konfigurationsdatei und somit das Bindeglied zwischen den Konfigurationseinstellungen und dem Programmcode. In der Klasse werden alle Einstellungen aus der Anwendungskonfigurationsdatei als Eigenschaftsmethoden veröffentlicht. Die benutzerspezifischen haben einen get- und set-Zweig, die anwendungsspezifischen implementieren nur get und liefern deshalb lediglich den Wert zurück.
Das Objekt MySettings kann vier Ereignisse auslösen, die Sie behandeln können:
| 1. | PropertyChanged |
| 2. | SettingChanging |
| 3. | SettingsLoaded |
| 4. | SettingsSaving |
Das SettingsSaving-Ereignis wird von der Save-Methode ausgelöst, bevor die Anwendungseinstellung gespeichert wird. Der zugeordnete Ereignishandler vom Typ CancelEventArgs kann den eingeleiteten Speichervorgang abbrechen.
Das SettingChanging-Ereignis tritt ein, bevor eine Anwendungseinstellung über den Indexer geändert wird. Der zweite Parameter des Ereignishandlers ermöglicht das Abrufen der zu ändernden Einstellung sowie des zugewiesenen Werts als auch darüber hinaus den Abbruch der Operation.
PropertyChanged und SettingsLoaded werden ausgelöst, wenn sich eine Eigenschaft ändert bzw. Einstellungen geladen werden.
Während sich im Namespace System.Configuration des .NET Frameworks 1.0/1.1 nur neun Klassen tummelten, hat sich die Anzahl in der Version 2.0 auf deutlich über 100 erhöht. Auch wenn Ihnen auch weiterhin die »alten« Klassen zur Verfügung stehen, empfiehlt die .NET-Dokumentation, auf die neuen zurückzugreifen. Hier nimmt die Klasse Configuration eine entscheidende Position ein. Configuration repräsentiert die Einstellungen einer Anwendung oder des Computers. Die Implementierung der Klasse berücksichtigt dabei, dass Anwendungen die Einstellungen in machine.config erben.
| Hinweis |
|
Wenn Sie Configuration, ConfigurationManager oder eine der anderen Klassen aus dem Namespace System.Configuration programmieren wollen, müssen Sie zuvor die Datei System.Configuration.dll unter Verweise einbinden. |
Configuration ist konstruktorlos. Das erinnert uns an die Klasse Graphics, deren Instanzen über andere Wege bereitgestellt werden. Ähnlich ist der Sachverhalt mit Configuration. Hier stellt uns die Klasse ConfigurationManager das entsprechende Configuration-Objekt zur Verfügung.
Configuration gibt uns mit seinen Eigenschaften und Methoden alle Mittel in die Hand, um Sektionen bzw. Sektionsgruppen, den physikalischen Pfad der Konfigurationsdatei abzurufen und Einstellungen zu speichern. In den beiden folgenden Tabellen sind die wichtigsten Eigenschaften und Methoden aufgeführt.
| Eigenschaft | Beschreibung |
| AppSettings | Ruft den Konfigurationsabschnitt des AppSettingsSection-Objekts ab. |
| ConnectionStrings | Ruft ein ConnectionStringsSection-Konfigurationsabschnittsobjekt ab. |
| FilePath | Ruft den physikalischen Pfad zu der Konfigurationsdatei ab. |
| Locations | Ruft die in diesem Configuration-Objekt definierten Speicherorte ab. |
| RootSectionGroup | Ruft die Stamm-ConfigurationSectionGroup ab. |
| SectionGroups | Ruft eine Auflistung der von dieser Konfiguration definierten Abschnittsgruppen ab. |
| Sections | Ruft eine Auflistung der von dieser Konfiguration definierten Abschnitte ab. |
| Methode | Beschreibung |
| GetSection | Gibt das angegebene ConfigurationSection-Objekt zurück. |
| GetSectionGroup | Ruft das angegebene ConfigurationSectionGroup-Objekt ab. |
| Save | Schreibt die Konfigurationseinstellungen in die aktuelle XML-Konfigurationsdatei. |
| SaveAs | Schreibt die Konfigurationseinstellungen in die angegebene XML-Konfigurationsdatei. |
Soweit die Eigenschaften und Methoden von Configuartion. Kommen wir nun zu den Membern von ConfigurationManager.
Die beiden einzigen Eigenschaften, die ConfigurationManager veröffentlicht, lauten AppSettings und ConnectionStrings, über die der Zugriff auf die Abschnitte <appSettings>- und <connectionStrings> möglich wird.
Zudem beschafft diese Klasse mit der Methode OpenExeConfiguration die Referenz auf ein Configuration-Objekt. Das ist deshalb besonders wichtig, weil ConfigurationManager selbst keine Methoden zum Speichern hat. Mit OpenMachineConfiguration ist der Zugriff auf die Datei machine.config sichergestellt.
| Eigenschaft | Beschreibung |
| AppSettings | Ruft die AppSettingsSection-Daten für die Standardkonfiguration ab. |
| ConnectionStrings | Ruft die ConnectionStringsSection-Daten für die Standardkonfiguration ab. |
| Methode | Beschreibung |
| GetSection | Ruft einen angegebenen Konfigurationsabschnitt für die Standardkonfiguration ab. |
| OpenExeConfiguration | Öffnet die angegebene Clientkonfigurationsdatei als Configuration-Objekt. |
| OpenMachine- Configuration | Öffnet die Computerkonfigurationsdatei auf dem aktuellen Computer als Configuration-Objekt. |
| RefreshSection | Aktualisiert den benannten Abschnitt. |
Wie Sie die Klassen Configuration und ConfigurationManager einsetzen können, zeige ich Ihnen in den beiden folgenden Abschnitten.
Einträge, die Sie in der Anwendungskonfigurationsdatei im Abschnitt <applicationSettings> vornehmen, sind nicht editierbar – zumindest aus dem Code einer Anwendung heraus. Man kann die Werte jedoch jederzeit ändern, indem man die Datei mit einem beliebigen Editor öffnet. Das ist insofern sinnvoll, dass nicht ein Benutzer von den Änderungen eines anderen Benutzers abhängig gemacht wird.
Nichtsdestotrotz könnten Sie als Entwickler auch einmal in die Situation kommen, aus dem Code heraus eine anwendungsweite Einstellung ändern zu wollen oder eine neue hinzuzufügen. Über die Hürde, die <applicationSettings> setzt, hilft die Festlegung eines anderen Abschnitts hinweg: <appSettings>. Das nun folgende Beispiel AppSettingsDemo zeigt, wie Sie mit den Klassen Configuration und ConfigurationManager die Einstellungen in <appSettings> beeinflussen können.
| ' --------------------------------------------------------- |
| ' Beispiel: ...\Kapitel 27\AppSettingsDemo |
| ' --------------------------------------------------------- |
| Imports System.Collections.Specialized |
| Imports System.Configuration |
| Module Module1 |
| Sub Main() |
| Console.WriteLine("Ursprüngliche 'appSettings'-Einstellungen:") |
| ShowAppSettings() |
| Console.WriteLine("Hinzufügen eines Eintrags:") |
| ' Bezeichner des Eintrags festlegen |
| Dim entry As String = "Nummer" & _ |
| ConfigurationManager.AppSettings.Count |
| ' appSettings-Eintrag hinzufügen |
| Dim config As Configuration = _ |
| ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None) |
| config.AppSettings.Settings.Add(entry, _ |
| DateTime.Now.ToLongTimeString()) |
| ' Ändern des ersten Eintrags |
| If (config.AppSettings.Settings.Count > 2) Then |
| config.AppSettings.Settings("Nummer" _ |
| & (config.AppSettings.Settings.Count – 3)).Value = _ |
| "veraltet" |
| End If |
| ' Speichern aller Änderungen |
| config.Save(ConfigurationSaveMode.Modified) |
| ' Erneutes Auslesen der Sektion 'appSettings' |
| ConfigurationManager.RefreshSection("appSettings") |
| Console.WriteLine() |
| Console.WriteLine("Geänderte 'appSettings'-Einstellungen:") |
| ShowAppSettings() |
| ' Anzeige des letzten Eintrags in der Konfigurationsdatei |
| Console.WriteLine() |
| Console.WriteLine("Der letzte Eintrag ist {0}", _ |
| ConfigurationManager.AppSettings(entry)) |
| Console.ReadLine() |
| End Sub |
| Sub ShowAppSettings() |
| Dim names As String() = _ |
| ConfigurationManager.AppSettings.AllKeys |
| Dim appStgs As NameValueCollection = _ |
| ConfigurationManager.AppSettings |
| Dim i As Integer |
| For i = 0 To appStgs.Count – 1 |
| Console.WriteLine("Nr.{0} – Wert: {1}", i, appStgs(i)) |
| Next |
| End Sub |
| End Module |
Wenn Sie die Anwendung testen wollen, sollten Sie sie nicht aus der Entwicklungsumgebung heraus starten, sondern das Kompilat. Ansonsten werden Sie den Effekt durch permanentes Neuschreiben der Datei app.config nicht sehen können. Die Ausgabe der Anwendung zeigt die folgende Abbildung.

Hier klicken, um das Bild zu Vergrößern
Abbildung 27.5 Die Ausgabe des Beispiels »AppSettingsDemo«
Bei jedem Neustart wird ein zusätzlicher Eintrag in die Anwendungskonfigurationsdatei geschrieben. Es handelt sich hierbei um die aktuelle Uhrzeit. Allerdings sollen nur die beiden letzten Starts auf diese Weise protokolliert werden, alle anderen Einträge werden mit »veraltet« überschrieben.
Für die Ausgabe des aktuellen Inhalts sorgt die Methode ShowAppSettings, in der zuerst alle namentlichen Einträge mit
| Dim names As String() = _ |
| ConfigurationManager.AppSettings.AllKeys |
abgefragt werden. ConfigurationManager.AppSettings liefert uns die Referenz auf ein Objekt vom Typ NameValueCollection. In diesem sind alle Elemente mit einem eindeutigen Schlüssel, einer Zeichenfolge, eingetragen. Alle Schlüssel werden als Array von der Eigenschaft AllKeys bereitgestellt. In einer Schleife werden alle Schlüssel abgegriffen und die zugeordneten Werte an der Konsole ausgegeben.
Als Collection stellt eine NameValueCollection passende Methoden bereit, um die Einträge zu manipulieren. Wir benutzen die Methode Add, um einen Neueintrag hinzuzufügen, und übergeben als Argumente den zuvor gebildeten neuen Elementnamen und anschließend die aktuelle Uhrzeit.
| config.AppSettings.Settings.Add(entry, _ |
| DateTime.Now.ToLongTimeString()) |
Da wir beabsichtigen, den Neueintrag auch zu speichern, benötigen wir ein Configuration-Objekt. Mit
| Dim config As Configuration = _ |
| ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None) |
holen wir uns die Referenz auf das benötigte Objekt, das die Anwendungskonfigurationsdatei verkörpert. Für das Speichern steht uns in Save die passende überladene Methode zur Verfügung.
config.Save(ConfigurationSaveMode.Modified)
Wir müssen nur sagen, welche Elemente wir zu speichern gedenken. Dazu erwartet die von uns bevorzugte Überladung die entsprechende Angabe. Die Enumeration Configuration-SaveMode beschreibt mit Full, Minimal und Modified alle denkbaren Fälle.
Eine weitere, sehr sinnvolle Neuerung im .NET Framework 2.0 ist das Element <connectionStrings>. Hier tragen Sie die Verbindungszeichenfolge für den Datenzugriff auf eine Datenquelle mittels ADO.NET ein. Sie können bei Bedarf mehrere Verbindungen beschreiben, auch mit unterschiedlichen Providern. Damit erhöht sich die Flexibilität der Anwendung und ermöglicht darüber hinaus auch, die Auswertung von Datenquellen zu berücksichtigen, deren Existenz zur Entwicklungszeit noch nicht bekannt ist.
| <?xml version="1.0" encoding="utf-8" ?> |
| <configuration> |
| <connectionStrings> |
| <add name="MySQLServer" |
| connectionString="Data Source=(local); |
| Initial catalog=northwind; |
| Trusted_Connection=yes" |
| providerName="System.Data.SqlClient"/> |
| <add name="MySQLServerOleDb" |
| connectionString="Provider=SQLOleDb; |
| Data Source=(local); |
| Initial catalog=pubs; |
| Trusted_Connection=yes" |
| providerName="System.Data.OleDb"/> |
| </connectionStrings> |
| </configuration> |
Mit dem <add>-Element wird eine Verbindungszeichenfolge beschrieben. connectionString, name und providerName sind Attribute des Elements. name macht die Verbindungszeichenfolge namentlich identifizierbar, und das optionale providerName-Attribut beschreibt den ADO.NET-Anbieter, der für den Zugriff auf den zugrunde liegenden Datenspeicher verwendet werden soll. Die Angabe der Datenquelle in connectionString erfolgt mit denselben providerspezifischen Angaben, die Sie auch dem Connection-Objekt von ADO.NET übergeben würden.
Der Zugriff auf die in einer Konfigurationsdatei definierten Verbindungszeichenfolgen ist sehr einfach. Etwas übertrieben mutet es im ersten Moment an, dass dafür mit ConnectionStringSettingsCollection eine andere Collection bereitgestellt wird, als es <appSettings> tut. Ein Element aus ConnectionStringSettingsCollection rufen Sie über die statische Eigenschaft ConnectionStrings der Klasse ConfigurationManager unter Übergabe des Bezeichners ab.
Jede Verbindungszeichenfolge in einer Anwendungskonfigurationsdatei wird durch die Klasse ConnectionStringSettings beschrieben, über deren Eigenschaften die Auswertung des Elements erfolgt. So kann beispielsweise über die Eigenschaft ConnectionString das gleichnamige Attribut ausgewertet werden, das maßgeblich für den Aufbau der Verbindung ist.
| Dim settings As ConnectionStringSettings = _ |
| ConfigurationManager.ConnectionStrings("MySQLServer") |
| Dim connectionString As String = settings.ConnectionString |
| Dim con As SqlConnection = _ |
| New SqlConnection(connectionString) |
Da Sie für jedes Verbindungselement einen anderen Datenprovider angeben können, interessiert der Inhalt des Attributs providerName.
| Dim css As ConnectionStringSettings |
| For Each css In ConfigurationManager.ConnectionStrings |
| If (css.ProviderName = "System.Data.OleDb") Then |
| ' Anweisungen |
| End If |
| If (css.ProviderName = "System.Data.SqlClient") Then |
| ' Anweisungen |
| End If |
| Next |
Ich bin Ihnen noch ein Beispiel schuldig geblieben. Vielleicht erinnern Sie sich, dass ich in Kapitel 14 beschrieben habe, wie Sie eine Assemblierung mit einem starken Namen erstellen und in den Global Assembly Cache (GAC) eintragen können. Ich hatte auch angedeutet, dass innerhalb einer Konfigurationsdatei einer kompilierten Anwendung von einer alten Komponente auf eine neuere Version »umgeschaltet« werden kann. Nun ist der Augenblick gekommen, Ihnen zu zeigen, wie Sie das realisieren können. Auf geht’s!
Wir stellen uns das folgende Szenario vor: Es wird eine Windows-Anwendung entwickelt. Die Anwendung ist auf Operationen angewiesen, die auch von anderen Anwendungen sinnvoll genutzt werden könnten. Deshalb ist es nahe liegend, für diese Operationen eine eigene Klassenbibliothek anzulegen und diese gleichzeitig mit einem starken Namen zu versehen. Die Version der Assembly sei 1.0.0.0. Die Assemblierung wird mit einer Installationsroutine verteilt und die Assembly bei der Installation im GAC (Global Assembly Cache) des Endanwenders registriert.
Im nächsten Schritt wird die Assembly so überarbeitet, dass die öffentliche Schnittstelle zwar abwärtskompatibel bleibt, sich aber die Codeimplementierung ändert. Die neue Version wird anschließend ebenfalls verteilt und in den GAC eingetragen. In diesem Moment liegen zwei Versionen derselben Komponente vor. Die Windows-Anwendung, in deren Manifest die alte Version der Assembly eingetragen ist, wird zur Laufzeit weiterhin auf die erste, nun aber veraltete Version zugreifen, denn mit dieser Vorgabe wurde die Anwendung kompiliert.
Vielleicht ist mit der neuen Version der Assembly aber ein Fehler im Programmcode der alten Version beseitigt worden. Dann wäre es sinnvoll, wenn die Windows-Anwendung die verbesserte Komponente nutzen könnte. Mit einer Anwendungskonfigurationsdatei ist das möglich, da deren Einträge die Entsprechungen im Manifest einer Anwendung überschreiben. Auf diese Weise zwingen wir die Anwendung, die überarbeitete Assembly aufzurufen – und das ohne Neukompilierung.
Im ersten Schritt schaffen wir uns zunächst die Grundlage und stellen die globale Assembly bereit. Dazu ist ein Projekt vom Typ Klassenbibliothek erforderlich.
| ' ------------------------------------------------------- |
| ' Beispiel: ...\Kapitel 27\ProcessServer |
| ' ------------------------------------------------------- |
| Public Class ProcessClass |
| Public Sub DoSomething() |
| MessageBox.Show("Version 1.0.0.0") |
| End Sub |
| End Class |
Weil sich die Assemblierung in den GAC eintragen soll, muss sie einen starken Namen haben. Dazu ist es notwendig, dem Projekt eine Schlüsseldatei hinzuzufügen. Diese können Sie mit dem SN-Tool erzeugen, z. B.:
| sn –k C:\<Projektverzeichnis>\MyKey.snk |
Die Schlüsseldatei sollte sich im Projektverzeichnis befinden und muss dem Projekt darüber hinaus auch ausdrücklich hinzugefügt werden (im Kontextmenü des Projekts über Hinzufügen Vorhandenes Element hinzufügen).
Eine Alternative zum SN-Tool liefert das Eigenschaftsfenster des Projekts. Wählen Sie hier die Lasche Signierung, und generieren Sie eine neue Schlüsseldatei. Optional können Sie hier auch eine bereits existierende einbinden. In der Datei AssemblyInfo.vb wird abschließend noch die Versionsnummer der Komponente unter AssemblyVersion eingetragen.
Jetzt kann das Projekt kompiliert werden. Als Ergebnis liegt abschließend eine DLL vor, die einen starken Namen hat und deshalb in den Global Assembly Cache eingetragen werden kann. Hierzu bietet sich ein Setup-Projekt an, mit dem Sie eine obligatorische Setup-Routine erstellen können.
Wenden wir uns nun zunächst der Windows-Anwendung zu, die auf die globale Komponente ProcessServer zugreift. Die Anwendung soll WinTestApp heißen und sofort nach dem Start die eingebundene Komponente aufrufen, die natürlich unter Verweise eingetragen sein muss.
| ' --------------------------------------------------------- |
| ' Beispiel: ...\Kapitel 27\WinTestApp |
| ' --------------------------------------------------------- 'Imports ProcessServer |
| Public Class Form1 |
| Private Sub Form1_Load(...) Handles MyBase.Load |
| Dim obj As ProcessClass = New ProcessClass |
| obj.DoSomething() |
| End Sub |
| End Class |
Es kommt nicht selten vor, dass eine einmal verteilte Komponente überarbeitet werden muss. Die Gründe hierfür können unterschiedlich sein:
| Es stellt sich heraus, dass die Komponente einen Bug enthält. |
| Der Programmcode wird optimiert, um beispielsweise ein besseres Laufzeitverhalten zu erreichen. |
| Die Komponente soll durch weitere Funktionalitäten ergänzt werden. |
Unabhängig davon, welcher Grund der auslösende Faktor ist, muss sichergestellt sein, dass auf einem Rechner, auf dem die alte Version der Komponente registriert ist, diese nicht blindlings durch die neue überschrieben wird.
Nehmen wir an, der Autor der Komponente ProcessServer möchte seine Komponente neu kompilieren, weil sich die Implementierung der Methode DoSomething verändert hat, z. B.:
| Public Class ProcessClass |
| Public Sub DoSomething() |
| MessageBox.Show("Version 1.0.1.0") |
| End Sub |
| End Class |
Die Datei AssemblyInfo.vb wird folgendermaßen geändert:
| <Assembly: AssemblyVersion("1.0.1.0")> |
Mit dem Attribut AssemblyVersion wird die neue Versionsnummer in das Manifest geschrieben. Da die überarbeitete Version abwärtskompatibel ist, wird nur die Build-Nummer erhöht. Anschließend kann die neue Version kompiliert werden.
Unabdingbare Voraussetzung dafür, dass nachher auch alles einwandfrei funktioniert, ist, dass die gleiche Schlüsseldatei verwendet wird wie für die nun alte Version der Assembly. Schlüsseldateien, die einen öffentlichen und einen privaten Schlüssel beschreiben, sind in ihrer Kombination global eindeutig. Damit authentifiziert sich der Entwickler als der Autor der Komponente. Würde ein anderer Entwickler – in guter oder böser Absicht – eine gleichnamige globale Komponente entwickeln und verteilen, würde sich diese (mindestens) im öffentlichen Schlüssel von der Originalkomponente unterscheiden. Die Anwendung greift jedoch aufgrund der Informationen im Manifest weiterhin auf das Original zu.
Auch die neue Version wird mit einer Setup-Routine verteilt.
Betrachten wir die Situation eines Anwenders, der sowohl die globale Komponente ProcessServer, Version 1.0.0.0, auf seinem Rechner registriert als auch die überarbeitete Fassung im globalen Assembly Cache eingetragen hat. Die Anwendung WinTestApp zeigt sich völlig unbeeindruckt von der Tatsache, dass nun zwei gleichnamige Komponenten im GAC installiert sind – sie verrichtet klaglos ihren Dienst und zeigt an der Konsole immer noch
| Version 1.0.0.0 |
an. Nichts anderes steht im Manifest, und eine abweichende Information gibt es (noch) nicht.
Standardmäßig wird immer auf die Komponente zugegriffen, die im Manifest angegeben ist, also schon zur Kompilierzeit bekannt war. Es stellt sich nun die Frage, wie einer Anwendung mitgeteilt werden kann, die neue Version aufzurufen und die alte zu ignorieren. Mit anderen Worten: Die Ausgabe der Anwendung WinTestApp soll
| Version 1.0.1.0 |
lauten – und das ohne Neukompilierung. Die Lösung lautet ganz einfach: In der Konfigurationsdatei muss eine entsprechende Umleitung erfolgen.
Wir wollen uns nun die Konfigurationsdatei ansehen, die es der Anwendung WinTestApp ermöglicht, auf die Version 1.0.1.0 der ProcessServer-Komponente zuzugreifen.
| <?xml version="1.0" encoding="utf-8" ?> |
| <configuration> |
| <runtime> |
| <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> |
| <dependentAssembly> |
| <assemblyIdentity name="ProcessServer" |
| publicKeyToken="7a26d8dbc8795f0c" |
| culture=""/> |
| <bindingRedirect oldVersion="1.0.0.0" |
| newVersion="1.0.1.0"/> |
| </dependentAssembly> |
| </assemblyBinding> |
| </runtime> |
| </configuration> |
| Hinweis |
|
Weiter oben haben Sie erfahren, dass es neben der Anwendungskonfigurationsdatei in jedem Fall auch eine Computerkonfigurationsdatei gibt, möglicherweise auch eine Herausgeberrichtliniendatei. Grundsätzlich kann in allen Konfigurationsdateien ein Assembly-Aufruf umgeleitet werden. Wollen Sie beispielsweise die Aufrufumleitung für alle Anwendungen einrichten, reicht ein Eintrag in der Computerkonfigurationsdatei (machine.config) aus. Die Struktur ist dabei dieselbe wie oben angegeben. |
Unter der Sektion <configuration> wird mit <runtime> ein neuer Abschnitt definiert. Zwischen <assemblyBinding> und </assemblyBinding> sind die Informationen aufgelistet, die für die Umleitung der Aufrufe an globale Assemblies verantwortlich sind. Jede Umleitung wird innerhalb eines eigenen <dependentAssembly>-Elements beschrieben.
| <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> |
| <!-- Bindungsinformationen für globale Assembly1 --> |
| <dependentAssembly> |
| <assemblyIdentity ... /> |
| <bindingRedirect ... /> |
| </dependentAssembly> |
| <!-- Bindungsinformationen für globale Assembly2 --> |
| <dependentAssembly> |
| <assemblyIdentity ... /> |
| <bindingRedirect ... /> |
| </dependentAssembly> |
| </assemblyBinding> |
Innerhalb des <dependentAssembly>-Abschnitts wird mit dem Subelement <assemblyIdentity> die Identität der globalen Assembly festgelegt, an die der Aufruf des Codes gerichtet werden soll. Die erforderlichen Informationen werden als Attribute festgelegt. Dazu gehören:
| der einfache Bezeichner der Assemblierung |
| die Kulturinformationen |
| der Token des öffentlichen Schlüssels |
In unserer Beispielkonfigurationsdatei lautet der Eintrag dementsprechend wie folgt:
| <assemblyIdentity name="ProcessServer" |
| publicKeyToken="7a26d8dbc8795f0c" |
| culture=""/> |
name, publicKeyToken und culture sind Attribute des Elements assemblyIdentity und spezifizieren exakt die globale Assembly. Die Angaben werden von der Common Language Runtime dazu benutzt, im GAC nach der Assembly zu suchen. Da im GAC aber nicht nur zwei, sondern auch x-beliebig viele Versionen der Assembly eingetragen sein könnten, muss man der CLR nur noch mitteilen, welche Version ersetzt werden soll, und insbesondere natürlich auch, durch welche. Dazu dient das Element <bindungRedirect>. Sehen wir uns die entscheidende Zeile in unserer Anwendungskonfigurationsdatei an:
| <bindingRedirect oldVersion="1.0.0.0" newVersion="1.0.1.0"/> |
Das Attribut oldVersion gibt die alte Version an, newVersion die neue. Damit erfüllt die Konfigurationsdatei ihre Aufgabe. Die Common Language Runtime findet die Angabe über die eingebundene globale Komponente und nutzt sie, während der Eintrag im Manifest der Anwendung zur Bedeutungslosigkeit degradiert wird.
Wie reagiert die Laufzeit, wenn unter oldVersion und/oder newVersion Angaben enthalten sind, die nicht den Einträgen im GAC entsprechen?
Die Angabe der alten, zu ersetzenden Komponentenversion spielt zunächst keine Rolle. Existiert die Version nicht, wird die Aufrufumleitung ignoriert und die notwendige Bindungsinformation aus dem Manifest bezogen. Etwas sensibler ist die Reaktion, wenn oldVersion einen gültigen Eintrag im Global Assembly Cache beschreibt und unter newVersion eine Versionsnummer angegeben ist, die im GAC nicht vertreten ist – es kommt zu einem Laufzeitfehler vom Typ FileLoadException.
|
Verweist das Attribut oldVersion auf eine Komponentenversion, die im GAC registriert ist, muss auch das Attribut newVersion eine bekannte Versionsnummer beinhalten. |
Häufig kommt es vor, dass mehrere ältere Versionen durch eine neue ersetzt werden können. Um einer Anwendungskonfigurationsdatei mehr Allgemeingültigkeit mit auf den Weg zu geben, kann man hinter oldVersion einen Versionsbereich festlegen, z. B.:
| <bindingRedirect oldVersion="3.0.3.0–3.0.7.0" newVersion="3.0.12.0"/> |
Auf der Buch-CD finden Sie alle in diesem Abschnitt erwähnten Projektdateien. Um die Auswirkung der Anwendungskonfigurationsdatei zu testen, müssen Sie zuerst die Setup-Routine des Projekts SetupProcessServerVersion1.0.0.0 ausführen. Hierbei handelt es sich um die Datei setup.exe, die im Unterordner Debug zu finden ist.
Bevor Sie das Testprojekt WinTestApp starten, sollten Sie in der Entwicklungsumgebung prüfen, ob der Verweis auf die Komponente ProcessServer richtig gesetzt ist. Kompilieren Sie anschließend die Windows-Anwendung, und führen Sie sie aus. Es sollte das Meldungsfenster der Assembly angezeigt werden mit Angabe der Version 1.0.0.0.
Installieren Sie nun die überarbeitete Version von ProcessServer (ProcessServerVer-sion1.0.1.0). Der erneute Start der EXE-Datei von WinTestApp beweist, dass die Anwendung weiterhin die ursprüngliche Fassung der globalen Assemblierung abruft.
Im gleichen Verzeichnis wie WinTestApp.exe habe ich auch die Vorlage für die Anwendungskonfigurationsdatei unter WinTestApp.exe.txt abgelegt. Sie müssen die Datei nur vorschriftsmäßig in WinTestApp.exe.config umbenennen. Dann sollte das erneute Ausführen von WinTestApp.exe dazu führen, dass die Laufzeit sich die neue Assembly aus dem GAC für den Aufruf der Operation besorgt.
Eine Herausgeberrichtliniendatei ist eine Konfigurationsdatei, die vom Komponentenentwickler zu einer Assembly kompiliert und im GAC installiert wird. Das Kompilat, die so genannte Herausgeberrichtlinien-Assembly, wird mit einer überarbeiteten globalen Assembly ausgeliefert. Herausgeberrichtliniendateien bieten sich insbesondere dann an, wenn sich in der älteren Version einer globalen Assembly ein Fehler herausgestellt hat und der Entwickler der globalen Assembly sicherstellen möchte, dass sich alle Anwendungen an die neue Version binden.
Der Inhalt der Herausgeberrichtliniendatei entspricht strukturell dem einer Anwendungskonfigurationsdatei. Der Name der Datei darf jedoch beliebig festgelegt werden. Für das Erzeugen der Herausgeberrichtlinien-Assembly müssen Sie allerdings auf ein Kommandozeilentool zurückgreifen, weil es einen entsprechenden Assistenten im Visual Studio 2005 nicht gibt. Bei dem Tool handelt es sich um den Assembly Linker al.exe, der im Verzeichnis
\Windows\Microsoft. NET\Framework\v<Frameworkversionsnummer>
An der Eingabeaufforderung muss ein verhältnismäßig komplexer Befehl abgesetzt werden, in dem zuerst der Name der Publisher-Richtliniendatei, also der XML-Datei, angegeben wird, daran anschließend der Name der resultierenden Herausgeberrichtlinien-Assembly und zum Schluss auch noch die Schlüsseldatei.
al /link:<Publisherrichtliniendatei> /out:<Ausgabedatei> /keyfile:<SNK-Datei>
Dem Bezeichner der Ausgabedatei, also der Herausgeberrichtlinien-Assembly, ist besondere Aufmerksamkeit zu widmen, da sie ein besonderes Format aufweisen muss. Er könnte beispielsweise lauten:
| policy.1.0.ProcessServer.dll |
Dem Bezeichner ist das Wort policy voranzustellen, dem sich jeweils durch einen Punkt getrennt aus der Versionsnummer der Assembly die Haupt- und Nebennummer anschließt. Danach wird noch die DLL-Datei der Assemblierung genannt.
Damit könnte der Befehl zur Generierung einer Publisher-Richtlinien-Assembly wie folgt lauten:
| al /link:new.config /out:policy.1.0.ProcessServer.dll /keyfile:MyKey.snk |
Eine Bindung an eine neue Assembly-Version im GAC umzuleiten, ist ein gravierender Eingriff auf dem Rechner eines Benutzers. Durch die Angabe der Schlüsseldatei, die natürlich dieselbe sein muss, mit der auch der starke Name der Assembly erzeugt wird, sichert der Entwickler seine Berechtigung für diesen Eingriff zu.
Die Herausgeberrichtlinien-Assembly muss zusammen mit der Assembly im GAC installiert werden. Dazu können Sie wieder das Tool gacutil mit dem Schalter /i benutzen, z. B.:
| gacutil /i policy.1.0.ProcessServer.dll |
Einfacher ist es auch hier, die Herausgeberrichtlinien-Assembly zusammen mit der überarbeiteten globalen Assembly in eine Installationsroutine des Windows Installers zu verpacken, um den Prozess benutzerfreundlich zu automatisieren.
| << zurück |
|
||||||
|
||||||
| ||||||